package com.xiao.tripmateai.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.xiao.tripmateai.exception.BusinessException;
import com.xiao.tripmateai.exception.ErrorCode;
import com.xiao.tripmateai.mapper.SpringAiChatMemoryMapper;
import com.xiao.tripmateai.model.domain.ChatMessage;
import com.xiao.tripmateai.model.domain.Conversation;
import com.xiao.tripmateai.model.domain.SpringAiChatMemory;
import com.xiao.tripmateai.model.dto.chat.UserChatCursorPageRequest;
import com.xiao.tripmateai.model.dto.chat.UserChatCursorPageResponse;
import com.xiao.tripmateai.model.dto.chat.UserChatHistoryRequest;
import com.xiao.tripmateai.service.SpringAiChatMemoryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import cn.hutool.core.util.StrUtil;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
* @author xiao
* @description 针对表【spring_ai_chat_memory】的数据库操作Service实现
* @createDate 2025-07-28 16:56:13
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class SpringAiChatMemoryServiceImpl extends ServiceImpl<SpringAiChatMemoryMapper, SpringAiChatMemory>
    implements SpringAiChatMemoryService {

    private final SpringAiChatMemoryMapper chatMemoryMapper;

    /**
     * 根据 id 获取用户历史对话记录
     * @param request
     * @return
     */
    @Override
    public List<Conversation> getUserConversations(UserChatHistoryRequest request) {
        // 1. 参数校验
        if (request == null || StrUtil.isBlank(request.getUserId())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户ID不能为空");
        }

        // 2. 构造用户ID前缀 (格式: "userId_")
        String userIdPrefix = request.getUserId() + "_";

        // 3. 使用QueryWrapper构建查询条件
        QueryWrapper<SpringAiChatMemory> queryWrapper = new QueryWrapper<>();
        // 使用likeRight进行右匹配查询 (相当于 LIKE 'userId_%')
        queryWrapper.likeRight("conversation_id", userIdPrefix);
        // 按时间戳升序排列，确保对话内消息顺序正确
        queryWrapper.orderByAsc("`timestamp`");

        // 4. 执行查询
        List<SpringAiChatMemory> records = chatMemoryMapper.selectList(queryWrapper);

        // 5. 按对话ID分组并转换结构
        Map<String, List<ChatMessage>> groupedMessages = records.stream()
                .collect(Collectors.groupingBy(
                        SpringAiChatMemory::getConversationId,
                        Collectors.mapping(
                                record -> new ChatMessage(
                                        record.getContent(),
                                        record.getType(),
                                        record.getTimestamp()
                                ),
                                Collectors.toList()
                        )
                ));

        // 6. 转换为对话列表 (按最新对话在前排序)
        return groupedMessages.entrySet().stream()
                .map(entry -> new Conversation(entry.getKey(), entry.getValue()))
                .sorted((c1, c2) -> {
                    // 提取时间戳从conversationId (格式: userId_timestamp)
                    try {
                        long time1 = Long.parseLong(c1.getConversationId().split("_")[1]);
                        long time2 = Long.parseLong(c2.getConversationId().split("_")[1]);
                        return Long.compare(time2, time1); // 倒序排序
                    } catch (Exception e) {
                        log.error("解析对话ID时间戳失败: {}, {}", c1.getConversationId(), c2.getConversationId(), e);
                        return 0; // 保持原顺序
                    }
                })
                .collect(Collectors.toList());
    }

    /**
     * 游标查询历史对话记录
     * @param request
     * @return
     */
    @Override
    public UserChatCursorPageResponse getUserConversationsByCursor(UserChatCursorPageRequest request) {
        // 1. 参数校验
        if (request == null || StrUtil.isBlank(request.getUserId())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户ID不能为空");
        }

        // 2. 构造用户ID前缀
        String userIdPrefix = request.getUserId() + "_";

        // 3. 使用游标查询对话ID列表
        List<String> conversationIds = getConversationIdsByCursor(
                userIdPrefix,
                request.getCursor(),
                request.getPageSize()
        );

        // 4. 如果没有查询到对话，直接返回空结果
        if (conversationIds.isEmpty()) {
            return new UserChatCursorPageResponse(Collections.emptyList(), null, false);
        }

        // 5. 查询这些对话的所有消息
        List<SpringAiChatMemory> records = getMessagesByConversationIds(conversationIds);

        // 6. 分组并转换为对话对象
        Map<String, List<ChatMessage>> groupedMessages = groupMessages(records);
        List<Conversation> conversations = buildConversations(conversationIds, groupedMessages);

        // 7. 计算下一页游标
        String nextCursor = conversationIds.get(conversationIds.size() - 1);
        boolean hasNext = hasNextPage(userIdPrefix, nextCursor);

        return new UserChatCursorPageResponse(conversations, nextCursor, hasNext);
    }

    /**
     * 根据游标获取对话ID列表
     */
    private List<String> getConversationIdsByCursor(String userIdPrefix, String cursor, int pageSize) {
        QueryWrapper<SpringAiChatMemory> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("DISTINCT conversation_id");
        queryWrapper.likeRight("conversation_id", userIdPrefix);

        // 如果有游标，查询比游标更早的对话
        if (StrUtil.isNotBlank(cursor)) {
            // 游标格式：userId_timestamp，按时间戳倒序
            queryWrapper.lt("conversation_id", cursor);
        }

        // 按conversation_id倒序（即按时间戳倒序）
        queryWrapper.orderByDesc("conversation_id");
        queryWrapper.last("LIMIT " + pageSize);

        return chatMemoryMapper.selectList(queryWrapper)
                .stream()
                .map(SpringAiChatMemory::getConversationId)
                .collect(Collectors.toList());
    }

    /**
     * 根据对话ID列表获取所有消息
     */
    private List<SpringAiChatMemory> getMessagesByConversationIds(List<String> conversationIds) {
        if (conversationIds.isEmpty()) {
            return Collections.emptyList();
        }

        QueryWrapper<SpringAiChatMemory> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("conversation_id", conversationIds);
        queryWrapper.orderByAsc("`timestamp`"); // 对话内消息按时间升序
        return chatMemoryMapper.selectList(queryWrapper);
    }

    /**
     * 将消息按对话分组
     */
    private Map<String, List<ChatMessage>> groupMessages(List<SpringAiChatMemory> records) {
        return records.stream()
                .collect(Collectors.groupingBy(
                        SpringAiChatMemory::getConversationId,
                        Collectors.mapping(
                                record -> new ChatMessage(
                                        record.getContent(),
                                        record.getType(),
                                        record.getTimestamp()
                                ),
                                Collectors.toList()
                        )
                ));
    }

    /**
     * 构建对话列表，保持原始顺序
     */
    private List<Conversation> buildConversations(
            List<String> conversationIds,
            Map<String, List<ChatMessage>> groupedMessages
    ) {
        return conversationIds.stream()
                .map(id -> new Conversation(id, groupedMessages.getOrDefault(id, Collections.emptyList())))
                .collect(Collectors.toList());
    }

    /**
     * 检查是否还有下一页
     */
    private boolean hasNextPage(String userIdPrefix, String lastCursor) {
        QueryWrapper<SpringAiChatMemory> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("1");
        queryWrapper.likeRight("conversation_id", userIdPrefix);
        queryWrapper.lt("conversation_id", lastCursor); // 查询比当前游标更早的对话
        queryWrapper.last("LIMIT 1");

        return chatMemoryMapper.selectCount(queryWrapper) > 0;
    }
}




